//==========================================================================
// Copyright (c) 2000-2008,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#include <regs.h>

LEAF(InitTlb)
    .set    noreorder;
    mtc0    zero, CP0_ENTRYLO0;
    mtc0    zero, CP0_ENTRYLO1;

    li      t8, PAGEMASK_4KB;
    mtc0    t8, CP0_PAGEMASK;

    li      t6, K1BASE;                     // tlbhi  = impossible vpn
    li      t5, MAX_TLB_ENTRY - 1;          // number of tlb entry

1:
    mtc0    t6, CP0_ENTRYHI;                // CP0_ENTRYHI
    mtc0    t5, CP0_INDEX;                  // CP0_INDEX
    addiu   t6, t6, PAGE_SIZE_ASM * 2;      // inc vpn
    tlbwi;
    subu    t5, 1;
    bgez    t5, 1b;
    nop;

    mtc0    zero, CP0_ENTRYHI;
    mtc0    zero, CP0_WIRED;                // set wired register
    li      t5, (MAX_TLB_ENTRY - 1);
    mtc0    t5, CP0_RANDOM;
    nop
    .set    reorder;
    jr      ra;
END(InitTlb)

LEAF(SetPageMask)
    .set    noreorder;
    mtc0    a0, CP0_PAGEMASK;
    nop;
    .set    reorder;
    jr      ra;
END(SetPageMask)

LEAF(FillRandomEntry)
    .set noreorder;
    mtc0    a0, CP0_ENTRYHI;
    mtc0    a1, CP0_ENTRYLO0;
    mtc0    a2, CP0_ENTRYLO1;
    nop;
    tlbwr;
    nop;
    .set reorder;
    jr      ra;
END(FillRandomEntry)

LEAF(FillAssignEntry)
    .set noreorder;
    mtc0    a0, CP0_INDEX;
    mtc0    a1, CP0_ENTRYHI;
    mtc0    a2, CP0_ENTRYLO0;
    mtc0    a3, CP0_ENTRYLO1;
    nop;
    tlbwi;
    nop;
    .set reorder;
    jr      ra;
END(FillAssignEntry)

LEAF(FindTlb)
    .set    noreorder;
    mfc0    t7, CP0_ENTRYHI;
    srl     a0, 13;
    sll     a0, 13;
    sll     t7, 24;
    srl     t7, 24;
    or      t7, a0;
    mtc0    t7, CP0_ENTRYHI;
    nop;
    tlbp;
    mfc0    v0, CP0_INDEX;
    nop;
    .set    reorder;
    jr      ra;
END(FindTlb)

LEAF(ReadTlb)
    .set    noreorder;
    mfc0    t7, CP0_ENTRYHI;        // save the entryHi
    mtc0    a0, CP0_INDEX;
    nop;
    tlbr;
    mfc0    t1, CP0_ENTRYHI;
    mfc0    t2, CP0_ENTRYLO0;
    mfc0    t3, CP0_ENTRYLO1;
    mfc0    t4, CP0_PAGEMASK;
    sw      t1, 0x0(a1);
    sw      t2, 0x0(a2);
    sw      t3, 0x0(a3);
    lw      a0, 0x10(sp);
    sw      t4, 0x0(a0);
    mtc0    t7, CP0_ENTRYHI;        // store the entryHi
    nop;
    .set    reorder;
    jr      ra;
END(ReadTlb)

LEAF(InvalidEntry)
    .set    noreorder;
    mfc0    t7, CP0_ENTRYHI;        // save the entryHi
    li      t1, K1BASE;
    mtc0    zero, CP0_ENTRYLO0;
    mtc0    zero, CP0_ENTRYLO1;
    mtc0    t1, CP0_ENTRYHI;
    mtc0    a0, CP0_INDEX;
    nop;
    tlbwi;
    mtc0    t7, CP0_ENTRYHI;        // store the entryHi
    nop;
    .set    reorder;
    jr      ra;
END(InvalidEntry)

.extern  s_nIndex

LEAF(FlushAllTlbs)
    .set    noreorder;
    mtc0    zero, CP0_ENTRYLO0;
    mtc0    zero, CP0_ENTRYLO1;

    la      t6, s_nIndex;
    lw      t7, 0(t6);
    li      t6, K1BASE;                     // tlbhi  = impossible vpn
    li      t5, MAX_TLB_ENTRY - 1;          // number of tlb entry

1:
    mtc0    t6, CP0_ENTRYHI;                // CP0_ENTRYHI
    mtc0    t5, CP0_INDEX;                  // CP0_INDEX
    addiu   t6, t6, PAGE_SIZE_ASM * 2;      // inc vpn
    tlbwi;
    subu    t5, 1;
    bne     t5, t7, 1b;
    nop;

    mtc0    zero, CP0_ENTRYHI;
    nop;
    .set    reorder;

    jr      ra;
END(FlushAllTlbs)
